package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.apis.article.ArticleFeignClient;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private ArticleFeignClient articleFeignClient;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private Tess4jClient tess4jClient;
    /**
     * 自媒体文章审核
     *
     * @param id 自媒体文章id
     */
    @Override
    public void autoScanWmNews(Integer id) {
        //1. 查询文章详情, 判断文章是否存在
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews==null){
            return;
        }
        //状态判断
        if (wmNews.getStatus()!=WmNews.Status.SUBMIT.getCode()){
            return;
        }
        //2. 抽取文章文本内容和图片数据
        Map<String, Object> textAndImages = extractTextAndImages(wmNews);

        //3. 内容审核
        String text = (String) textAndImages.get("text");
        //3.0 敏感词审核
        boolean isSensitive = handleSensitiveScan(wmNews,text);
        if(!isSensitive){
            return;
        }

        //3.1 文本审核
        boolean textScan = handleTextScan(wmNews, text);
        if (!textScan) {
            return;
        }

        //3.2 图片审核
        List<String> images = (List<String>) textAndImages.get("images");
        boolean imageScan = handleImagesScan(wmNews, images);
        if (!imageScan) {
            return;
        }
        //4. 发布文章
        //4.1 远程发布文章
        ResponseResult<Long> responseResult = saveArticle(wmNews);
        if (responseResult.getCode()!=200){
            throw new RuntimeException("调用远程文章服务出现异常:"+responseResult.getErrorMessage());
        }
        //4.2 修改数据状态 , 回填文章id
        wmNews.setArticleId(responseResult.getData());
        updateStatus(wmNews,WmNews.Status.PUBLISHED,"文章发布成功");
    }

    //自定义敏感词审核
    private boolean handleSensitiveScan(WmNews wmNews,String content) {
        if (StringUtils.isBlank(content)){
            return true;
        }
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (map.size() > 0) {
            updateStatus(wmNews, WmNews.Status.FAIL, "文本或图片内容中包含敏感词");
            return false;
        }

        return true;
    }


    /**
     * 文本审核
     * @param wmNews
     * @param text
     * @return
     */
    private boolean handleTextScan(WmNews wmNews, String text) {
        if (StringUtils.isEmpty(text)) {
            return true;
        }
        //使用阿里云审核

        try {
            //使用阿里云进行文本审核  pass    review
            Map result = greenTextScan.greeTextScan(text);
            //审核失败, 内容中包含违规信息
            if ("block".equals(result.get("suggestion"))) {
                updateStatus(wmNews, WmNews.Status.FAIL, "文章内容中包含违规信息");
                return false;
            }
            //需要进行人工审核
            if ("review".equals(result.get("suggestion"))) {
                updateStatus(wmNews, WmNews.Status.ADMIN_AUTH, "文章内容中包含不确定信息");
                return false;
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            updateStatus(wmNews, WmNews.Status.ADMIN_AUTH, "阿里云文本审核失败:" + e.getMessage());
            return false;
        }
    }

    private void updateStatus(WmNews wmNews, WmNews.Status status, String msg) {
        wmNews.setStatus(status.getCode());
        wmNews.setReason(msg);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 抽取文章文本内容和图片数据
     * @param wmNews
     * @return
     */
    private Map<String, Object> extractTextAndImages(WmNews wmNews) {
        String content = wmNews.getContent();
        List<Map> maps = JSON.parseArray(content, Map.class);
        StringBuilder text = new StringBuilder();
        ArrayList<String> images = new ArrayList<>();
//        封装内容中的图片和文字
        for (Map map : maps) {
            if ("text".equals(map.get("type"))){
                text.append(map.get("value")).append(",");
            }
            if ("image".equals(map.get("type"))){
                images.add((String) map.get("value"));
            }
        }
//        封装标题和封面图片
        text.append(wmNews.getTitle());
        if (StringUtils.isNotBlank(wmNews.getImages())){
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }
        Map map=new HashMap();
        map.put("text",text.toString());
        map.put("images",images);
        return map;
    }

    /**
     * 图片审核
     *
     * @param wmNews
     * @param images
     * @return
     */
    private boolean handleImagesScan(WmNews wmNews, List<String> images) {
        //1. 判断图片是否存在
        if (CollectionUtils.isEmpty(images)) {
            return true;
        }
        try {
            //2. 下载图片字节
            List<byte[]> list = images.stream().map(image -> fileStorageService.downLoadFile(image)).collect(Collectors.toList());

            //图片中文字识别审核
            for (byte[] bytes : list) {
                ByteArrayInputStream is = new ByteArrayInputStream(bytes);
                BufferedImage bufferedImage = ImageIO.read(is);
                String ocr = tess4jClient.doOCR(bufferedImage);

                boolean sensitiveScan = handleSensitiveScan(wmNews, ocr);
                if (!sensitiveScan) {
                    return false;
                }

            }

            //3. 调用阿里云审核图片  pass block review
            Map<String, String> result = greenImageScan.imageScan(list);

            //审核失败, 图片中包含违规信息
            if ("block".equals(result.get("suggestion"))) {
                updateStatus(wmNews, WmNews.Status.FAIL, "图片内容中包含违规信息");
                return false;
            }
            //需要进行人工审核
            if ("review".equals(result.get("suggestion"))) {
                updateStatus(wmNews, WmNews.Status.ADMIN_AUTH, "图片中包含不确定信息");
                return false;
            }

            return true;
        } catch (Exception exception) {
            exception.printStackTrace();
            updateStatus(wmNews, WmNews.Status.ADMIN_AUTH, "阿里云图片审核失败:" + exception.getMessage());
            return false;
        }
    }

    /**
     * 发布文章
     * @param wmNews
     */
    private ResponseResult<Long> saveArticle(WmNews wmNews) {
        //1. 封装参数
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);
        //处理数据  id  authorId authorName  channelName  layout
        if (wmNews.getArticleId()!=null){
            //设置文章id
            articleDto.setId(wmNews.getArticleId());
        }
        //设置自媒体用户id
        articleDto.setAuthorId(wmNews.getUserId().longValue());
        //根据自媒体用户id查询用户
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getName());
        }

        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel != null) {
            //设置频道名称
            articleDto.setChannelName(wmChannel.getName());
        }
        //文章布局
        articleDto.setLayout(wmNews.getType());

        //2. 调用远程feign接口发布文章
        return articleFeignClient.save(articleDto);
    }
}
